use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};
use wasmer::{imports, Instance, Module, Store, Value as WasmerValue};

use model_graph_types::{
    container::workflow::{
        WasmStatement, WorkflowBlockExecuteResult, WorkflowBlockExecuteResultBuilder,
        WorkflowBlockExecuteResultStatus,
    },
    modeling::Value,
};

use crate::workflow::{
    blocks::statements::_utils::query_value_with_variables, context::WorkflowContext,
};

pub async fn execute(
    statement: &WasmStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<WorkflowBlockExecuteResult> {
    let result = _execute(statement, context).await;

    match result {
        Ok(v) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("source")
            .result(v)
            .build()?),
        Err(err) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("fail-branch")
            .build()?),
    }
}

pub async fn _execute(
    statement: &WasmStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<HashMap<String, Value>> {
    let file = query_value_with_variables(&statement.file, context.clone()).await?;
    let function_name =
        query_value_with_variables(&statement.function_name, context.clone()).await?;

    let arguments = &statement.arguments;
    let output = &statement.outputs;

    tracing::debug!("WASM执行:[{}][{}]", file, function_name);
    let module_wat = r#"
    (module
      (type $t0 (func (param i32) (result i32)))
      (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
        local.get $p0
        i32.const 1
        i32.add))
    "#;

    let mut store = Store::default();
    let module = Module::new(&store, &module_wat)?;
    //
    let import_object = imports! {};
    let instance = Instance::new(&mut store, &module, &import_object)?;

    let add_one = instance.exports.get_function("add_one")?;
    let result = add_one.call(&mut store, &[WasmerValue::I32(42)])?;

    let mut result: HashMap<String, Value> = HashMap::new();
    //
    Ok(result)
}
